using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace GCFlashControl
{
	[DefaultProperty("Movie"),
   ToolboxData("<{0}:GCFlashControl runat=server Width=1 Height=1 SwfMovie=movie MajorVersion=6 MinorVersion=0 RequiredRevision=65></{0}:GCFlashControl>"),
	 ToolboxBitmap(typeof(GCFlashControl), "GCFlashControl.GCFlashControl.bmp"),
	 Designer("GCFlashControl.Design.GCFlashControlDesigner")]
	public class GCFlashControl : WebControl, INamingContainer
	{
		#region Private Member Variables
		private NoData _NoFlashData = null;
		private string _NoFlashMarkup;
		private ITemplate _NoFlashTemplate = null;
		private NoData _NoScriptData = null;
		private string _NoScriptMarkup;
		private ITemplate _NoScriptTemplate = null;
		#endregion

		public enum Alignments { middle, left, right, top, bottom };
		public enum Qualities { low, medium, high, autoLow, autoHigh, best };
		public enum Scales { showAll, noBorder, exactFit, noScale};
		public enum ScaledAlignments { middle, left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight };
		public enum ScriptAccessValues { sameDomain, never, always };
		public enum WindowModes { window, direct, gpu, transparent, opaque };

		#region Properties
		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue("")]
		[Localizable(true)]
		public string AbsolutePath
		{
			get
			{
				String s = (String)ViewState["AbsolutePath"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["AbsolutePath"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(Alignments.middle)]
		[Localizable(true)]
		public Alignments Align
		{
			get
			{
				object o = (object)ViewState["Align"];
				return ((o == null) ? Alignments.middle : (Alignments)o);
			}

			set
			{
				ViewState["Align"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(false)]
		[Localizable(true)]
		public bool AllowFullScreen
		{
			get
			{
				object o = ViewState["AllowFullScreen"];
				if (o == null)
					return false;

				return (bool)o;
			}

			set
			{
				ViewState["AllowFullScreen"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(ScriptAccessValues.sameDomain)]
		[Localizable(true)]
		public ScriptAccessValues AllowScriptAccess
		{
			get
			{
				object o = (object)ViewState["AllowScriptAccess"];
				return ((o == null) ? ScriptAccessValues.sameDomain : (ScriptAccessValues)o);
			}

			set
			{
				ViewState["AllowScriptAccess"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue("http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,124,0")]
		[Localizable(true)]
		public string CodeBase
		{
			get
			{
				String s = (String)ViewState["CodeBase"];
				return ((s == null) ? "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,124,0" : s);
			}

			set
			{
				ViewState["CodeBase"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(false)]
		[Localizable(true)]
		public bool DeviceFont
		{
			get
			{
				object o = ViewState["DeviceFont"];
				if (o == null)
					return false;

				return (bool)o;
			}

			set
			{
				ViewState["DeviceFont"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue("")]
		[Localizable(true)]
		public string DivId
		{
			get
			{
				String s = (String)ViewState["DivId"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["DivId"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(false)]
		[Localizable(true)]
		public bool EnableExpressInstall
		{
			get
			{
				object o = ViewState["EnableExpressInstall"];
				if (o == null)
					return false;

				return (bool)o;
			}

			set
			{
				ViewState["EnableExpressInstall"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue("")]
		[Localizable(true)]
		public string Id
		{
			get
			{
				String s = (String)ViewState["Id"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["Id"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(false)]
		[Localizable(true)]
		public bool Loop
		{
			get
			{
				object o = ViewState["Loop"];
				if (o == null)
					return true;

				return (bool)o;
			}

			set
			{
				ViewState["Loop"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(6)]
		[Localizable(true)]
		public int MajorVersion
		{
			get
			{
				object o = ViewState["MajorVersion"];
				return ((o == null) ? 6 : Convert.ToInt32(o));
			}

			set
			{
				ViewState["MajorVersion"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(0)]
		[Localizable(true)]
		public int MinorVersion
		{
			get
			{
				object o = ViewState["MinorVersion"];
				return ((o == null) ? 0 : Convert.ToInt32(o));
			}

			set
			{
				ViewState["MinorVersion"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(true)]
		[Localizable(true)]
		public bool Menu
		{
			get
			{
				object o = ViewState["Menu"];
				if (o == null)
					return true;

				return (bool)o;
			}

			set
			{
				ViewState["Menu"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue("")]
		[Localizable(true)]
		public string Name
		{
			get
			{
				String s = (String)ViewState["Name"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["Name"] = value;
			}
		}

		[
		Browsable(false),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public NoData NoFlashData
		{
			get
			{
				this.EnsureChildControls();
				return _NoFlashData;
			}
		}

		[
		Browsable(false),
		DefaultValue(null),
		Description("The no flash template."),
		TemplateContainer(typeof(NoData)),
		PersistenceMode(PersistenceMode.InnerProperty)
		]
		public virtual ITemplate NoFlashTemplate
		{
			get
			{
				return _NoFlashTemplate;
			}
			set
			{
				_NoFlashTemplate = value;
			}
		}

		[
		Browsable(false),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public NoData NoScriptData
		{
			get
			{
				this.EnsureChildControls();
				return _NoScriptData;
			}
		}

		[
		Browsable(false),
		DefaultValue(null),
		Description("The no script template."),
		TemplateContainer(typeof(NoData)),
		PersistenceMode(PersistenceMode.InnerProperty)
		]
		public virtual ITemplate NoScriptTemplate
		{
			get
			{
				return _NoScriptTemplate;
			}
			set
			{
				_NoScriptTemplate = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(true)]
		[Localizable(true)]
		public bool Play
		{
			get
			{
				object o = ViewState["Play"];
				if (o == null)
					return true;

				return (bool)o;
			}

			set
			{
				ViewState["Play"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue("http://www.adobe.com/go/getflashplayer")]
		[Localizable(true)]
		public string PlugInsPage
		{
			get
			{
				String s = (String)ViewState["PlugInsPage"];
				return ((s == null) ? "http://www.adobe.com/go/getflashplayer" : s);
			}

			set
			{
				ViewState["PlugInsPage"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(Qualities.high)]
		[Localizable(true)]
		public Qualities Quality
		{
			get
			{
				object o = ViewState["Quality"];
				if (o == null)
					return Qualities.high;
				return (Qualities)o;
			}

			set
			{
				ViewState["Quality"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(65)]
		[Localizable(true)]
		public int RequiredRevision
		{
			get
			{
				object o = (object)ViewState["RequiredRevision"];
				return ((o == null) ? 65 : Convert.ToInt32(o));
			}

			set
			{
				ViewState["RequiredRevision"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(ScaledAlignments.middle)]
		[Localizable(true)]
		public ScaledAlignments SAlign
		{
			get
			{
				object o = (object)ViewState["SAlign"];
				return ((o == null) ? ScaledAlignments.middle : (ScaledAlignments)o);
			}

			set
			{
				ViewState["SAlign"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(Scales.showAll)]
		[Localizable(true)]
		public Scales Scale
		{
			get
			{
				object o = ViewState["Scale"];
				if (o == null)
					return Scales.showAll;
				return (Scales)o;
			}

			set
			{
				EnsureChildControls();
				ViewState["Scale"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue("")]
		[Localizable(true)]
		public string Source
		{
			get
			{
				String s = (String)ViewState["Source"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["Source"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue("")]
		[Localizable(true)]
		public string SwfMovie
		{
			get
			{
				String s = (String)ViewState["Movie"];
				return ((s == null) ? String.Empty : s);
			}

			set
			{
				ViewState["Movie"] = value;
			}
		}

		[Bindable(true)]
		[Category("Misc")]
		[DefaultValue(WindowModes.window)]
		[Localizable(true)]
		public WindowModes WindowMode
		{
			get
			{
				object o = ViewState["WMode"];
				if (o == null)
					return WindowModes.window;
				return (WindowModes)o;
			}

			set
			{
				ViewState["WMode"] = value;
			}
		}

		// For composite controls, the Controls collection needs to be overriden to
		// ensure that the child controls have been created before the Controls
		// property can be modified by the page developer...
		public override ControlCollection Controls
		{
			get
			{
				this.EnsureChildControls();
				return base.Controls;
			}
		}
		#endregion

		#region Internal Design Helper Methods
		// This internal helper method is used by the designer to set the NoData instances
		// to a specified object.  Note that the public NoData properties are read-only...
		internal void AddNoFlashData(NoData nfd)
		{
			this._NoFlashData = nfd;
		}
		internal void AddNoScriptData(NoData nsd)
		{
			this._NoScriptData = nsd;
		}
		#endregion

		#region Overridden Control Members
		protected override void CreateChildControls()
		{
			Controls.Clear();		// clear out the control hierarchy
			
			// get the NoFlash template
			ITemplate template = this.NoFlashTemplate;
			if (template == null)
			{
				//// use the default javascript that gets generated by Adobe
				//_NoFlashMarkup = "Alternate HTML content should be placed here."
				//                    + "This content requires the Adobe Flash Player."
				//                    + "<a href=\"http://www.adobe.com/go/getflashplayer/\">Get Flash</a>";
			}
			else
			{
				// create a new NoFlashData instance
				this._NoFlashData = new NoData();

				// instantiate the NoData in the template
				template.InstantiateIn(_NoFlashData);
				// A normal templated control would add the control hierarchy here so it appears on the form. 
				if (this.Site != null && this.Site.DesignMode)
				{
					Controls.Add(_NoFlashData);
				}
				// But this isn't a normal control. So just get the html markup that
				// would be generated if the template was used like a normal control.
				System.Text.StringBuilder sb = new System.Text.StringBuilder();
				System.IO.StringWriter txt = new System.IO.StringWriter(sb);
				HtmlTextWriter html = new HtmlTextWriter(txt);
				this._NoFlashData.RenderControl(html);
				if (sb.Length > 0) _NoFlashMarkup = sb.ToString();
			}

			// get the NoScript template
			template = this.NoScriptTemplate;
			if (template != null)
			{
				// create a new NoData instance
				this._NoScriptData = new NoData();

				// instantiate the NoData in the template. This builds the markup.
				template.InstantiateIn(this._NoScriptData);
				// A normal templated control would add the control hierarchy here so it appears on the form. 
				if (this.Site != null && this.Site.DesignMode)
				{
					Controls.Add(this._NoScriptData);
				}
				// But this isn't a normal control. So just get the html markup that
				// would be generated if the template was used like a normal control.
				System.Text.StringBuilder sb = new System.Text.StringBuilder();
				System.IO.StringWriter txt = new System.IO.StringWriter(sb);
				HtmlTextWriter html = new HtmlTextWriter(txt);
				this._NoScriptData.RenderControl(html);
				if (sb.Length > 0) _NoScriptMarkup = sb.ToString();
			}
		}

		public override void DataBind()
		{
			// Create the child controls...
			CreateChildControls();
			this.ChildControlsCreated = true;		// mark that the children have been created			

			base.DataBind();		// nothing to bind, but call the DataBind method anyway
		}

		protected override void OnPreRender(EventArgs e)
		{
			StringBuilder sb = new StringBuilder();
			String sBasePath = AbsolutePath;
			if (!String.IsNullOrEmpty(sBasePath))
				if (!sBasePath.EndsWith("/"))
					sBasePath = sBasePath + "/";

			base.OnPreRender(e);

			if (!Page.ClientScript.IsClientScriptIncludeRegistered("AC_OETags"))
			{
				Page.ClientScript.RegisterClientScriptInclude("AC_OETags", String.Format("{0}AC_OETags.js", sBasePath));
			}

			if (!Page.ClientScript.IsStartupScriptRegistered(this.Page.GetType(), "AC_OEGlobals"))
			{
				sb.AppendLine("// -----------------------------------------------------------------------------");
				sb.AppendLine("// Globals");
				sb.AppendLine("// Major version of Flash required");
				sb.AppendLine(String.Format("var requiredMajorVersion = {0};", MajorVersion.ToString()));
				sb.AppendLine("// Minor version of Flash required");
				sb.AppendLine(String.Format("var requiredMinorVersion = {0};", MinorVersion.ToString()));
				sb.AppendLine("// Revision of Flash required");
				sb.AppendLine(String.Format("var requiredRevision = {0};", RequiredRevision.ToString()));
				sb.AppendLine("// -----------------------------------------------------------------------------");

				sb.AppendLine(String.Format("var expressInstallEnabled = {0};", ToLower(EnableExpressInstall.ToString())));
				sb.AppendLine("var hasMinInstallVersion = DetectFlashVer(6, 0, 65);");
				sb.AppendLine("var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);");

				Page.ClientScript.RegisterStartupScript(this.Page.GetType(), "AC_OEGlobals", sb.ToString(), true);
			}

			if (!Page.ClientScript.IsStartupScriptRegistered(this.Page.GetType(), "AC_OEExpressInstall"))
			{
				sb.Length = 0;

				sb.AppendLine("if (expressInstallEnabled && hasMinInstallVersion && !hasRequestedVersion) {");

				sb.AppendLine("	// MMdoctitle is the stored document.title value used by the installation process to close the window that started the process");
				sb.AppendLine("	// This is necessary in order to close browser windows that are still utilizing the older version of the player after installation has completed");
				sb.AppendLine("	// DO NOT MODIFY THE FOLLOWING FOUR LINES");
				sb.AppendLine("	// Location visited after installation is complete if installation is required");
				sb.AppendLine("	var MMPlayerType = (isIE == true) ? \"ActiveX\" : \"PlugIn\";");
				sb.AppendLine("	var MMredirectURL = window.location;");
				sb.AppendLine("	document.title = document.title.slice(0, 47) + \" - Flash Player Installation\";");
				sb.AppendLine("	var MMdoctitle = document.title;");

				sb.AppendLine("	AC_FL_RunContent(");
				sb.AppendLine(String.Format("		\"src\", \"{0}playerProductInstall\",", sBasePath));
				sb.AppendLine("		\"FlashVars\", \"MMredirectURL=\"+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle,");
				sb.AppendLine("		\"width\", \"550\",");
				sb.AppendLine("		\"height\", \"300\",");
				sb.AppendLine("		\"align\", \"middle\",");
				sb.AppendLine("		\"id\", \"detectionExample\",");
				sb.AppendLine("		\"quality\", \"high\",");
				sb.AppendLine("		\"bgcolor\", \"#3A6EA5\",");
				sb.AppendLine("		\"name\", \"detectionExample\",");
				sb.AppendLine("		\"allowScriptAccess\",\"always\",");
				sb.AppendLine("		\"type\", \"application/x-shockwave-flash\",");
				sb.AppendLine("		\"pluginspage\", \"http://www.adobe.com/go/getflashplayer\");");
				sb.AppendLine("}");
				Page.ClientScript.RegisterStartupScript(this.Page.GetType(), "AC_OEExpressInstall", sb.ToString(), true);
			}

			sb.Length = 0;

			sb.AppendLine("if(hasRequestedVersion) {  // if we've detected an acceptable version");

			sb.AppendLine("	// embed the flash movie");
			sb.AppendLine("	AC_FL_RunContent(");
			sb.AppendLine(String.Format("		'codebase', '{0}',", ToLower(CodeBase)));
			sb.AppendLine(String.Format("		'width', '{0}',", this.Width.ToString()));
			sb.AppendLine(String.Format("		'height', '{0}',", this.Height.ToString()));
			sb.AppendLine(String.Format("		'src', '{0}',", ToLower(Source)));
			sb.AppendLine(String.Format("		'quality', '{0}',", ToLower(Quality.ToString())));
			sb.AppendLine(String.Format("		'pluginspage', '{0}',", ToLower(PlugInsPage)));
			sb.AppendLine(String.Format("		'align', '{0}',", ToLower(Align.ToString())));
			sb.AppendLine(String.Format("		'play', '{0}',", ToLower(Play.ToString())));
			sb.AppendLine(String.Format("		'loop', '{0}',", ToLower(Loop.ToString())));
			sb.AppendLine(String.Format("		'scale', '{0}',", Scale.ToString()));
			sb.AppendLine(String.Format("		'wmode', '{0}',", WindowMode.ToString()));
			sb.AppendLine(String.Format("		'devicefont', '{0}',", ToLower(DeviceFont.ToString())));
			sb.AppendLine(String.Format("		'id', '{0}',", Id));
			if (!BackColor.IsEmpty)
				sb.AppendLine(String.Format("		'bgcolor', '{0}',", BackColor.ToString()));
			sb.AppendLine(String.Format("		'name', '{0}',", Name));
			sb.AppendLine(String.Format("		'menu', '{0}',", ToLower(Menu.ToString())));
			sb.AppendLine(String.Format("		'allowFullScreen', '{0}',", ToLower(AllowFullScreen.ToString())));
			sb.AppendLine(String.Format("		'allowScriptAccess','{0}',", AllowScriptAccess.ToString()));
			sb.AppendLine(String.Format("		'movie', '{0}{1}',", sBasePath, SwfMovie));
			sb.AppendLine(String.Format("		'salign', '{0}',", SAlign.ToString()));
			sb.AppendLine(String.Format("		'divid', '{0}'", DivId));
			sb.AppendLine("	); //end AC code");
			if (!String.IsNullOrEmpty(_NoFlashMarkup))
			{
				sb.AppendLine("} else if (!expressInstallEnabled) {  // flash is too old or we can't detect the plugin");
				sb.AppendLine(String.Format("	var alternateContent = '{0}';", CutWhitespace(_NoFlashMarkup.Replace("'", "\\'"))));
				if (String.IsNullOrEmpty(DivId)) {
					sb.AppendLine("	document.write(alternateContent);  // insert non-flash content");
				} else {
					sb.AppendLine(String.Format("    var div = document.getElementById('{0}');", DivId));
					sb.AppendLine("    if (div != null) {");
					sb.AppendLine("        div.innerHTML = str;");
					sb.AppendLine("    }");
				}
			}
			sb.AppendLine("}");
			Page.ClientScript.RegisterStartupScript(this.Page.GetType(), String.Format("GCFlashControl_{0}", this.Id), sb.ToString(), true);

		}

		protected override void Render(HtmlTextWriter writer)
		{
			if (this.Site != null && this.Site.DesignMode == true)
			{
				base.Render(writer);
			}
			else
			{
				if (!String.IsNullOrEmpty(_NoScriptMarkup))
				{
					writer.WriteLine("<noscript>");
					writer.WriteLine(_NoScriptMarkup);
					writer.WriteLine("</noscript>");
				}
			}
		}
		#endregion

		#region Private Methods
		private string CutWhitespace(string inStr)
		{
			if (String.IsNullOrEmpty(inStr))
				return inStr;
			return Regex.Replace(inStr, @"\s+", " ").Trim();
		}

		private string ToLower(object inStr)
		{
			if (!(inStr is string))
				return String.Empty;
			if (String.IsNullOrEmpty((string)inStr))
				return String.Empty;
			return ((string)inStr).ToLower();
		}
		#endregion
	}
}
